package com.tenebrous.jestic.controller.framwork.meber.author;

import com.alibaba.fastjson.JSON;
import com.tenebrous.jestic.compents.annotations.Weblog;
import com.tenebrous.jestic.compents.annotations.WeblogEnum;
import com.tenebrous.jestic.compents.exception.BizException;
import com.tenebrous.jestic.controller.SupperController;
import com.tenebrous.jestic.entity.framwork.meber.author.AuthRoleUser;
import com.tenebrous.jestic.entity.framwork.meber.organ.OrgUser;
import com.tenebrous.jestic.entity.framwork.meber.organ.OrgUserAccount;
import com.tenebrous.jestic.entity.framwork.system.SysLogLogin;
import com.tenebrous.jestic.service.framwork.meber.author.AuthRoleService;
import com.tenebrous.jestic.service.framwork.meber.organ.OrgUserService;
import com.tenebrous.jestic.service.framwork.system.SysLogService;
import com.tenebrous.jestic.utils.RandomNumberUtil;
import com.tenebrous.jestic.utils.RedisTemplateUtil;
import com.rain.ops.sdk.dto.ApiResult;
import com.rain.ops.sdk.utils.SnowFlakeUtils;
import com.rain.ops.sdk.utils.UUIDUtils;
import com.rain.ops.sdk.utils.VcodeUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.DigestUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.util.*;

@Slf4j
@Validated
@RestController
@RequestMapping("/author/auth")
public class AuthController extends SupperController {

    @Autowired
    private AuthRoleService roleService;

    @Autowired
    private OrgUserService userService;

    @Autowired
    private SysLogService logService;

    @Autowired
    private RedisTemplateUtil redisTemplateUtil;

    @Value("${sdk.tencent.sms.login-code-notice-template-id}")
    private String LOGIN_CODE_NOTICE_TEMPLATE_ID;

    /**
     * 与红河州对接
     *
     * @param username
     * @return
     */
    @PostMapping("/sso/account/merge")
    @Weblog(description = "请求登录验证", method = WeblogEnum.UPDATE)
    public ApiResult mergeSsoAccount(@NotBlank String username) {
        OrgUser ouser = this.userService.getByUsername(username);
        if (ouser == null) {
            ouser = new OrgUser();
            ouser.setId(UUIDUtils.randomUUID());
            ouser.setDstate(1);
            ouser.setEstate("在职");
            ouser.setCreateDate(new Date());
            ouser.setRealname(username);
            ouser.setDepartmentid("F818D71E25D347A1A491367DE6EB4E32");
            ouser.setRemark("红河林草");
            userService.save(ouser);

            OrgUserAccount it = new OrgUserAccount();
            it.setId(ouser.getId());
            it.setUserid(ouser.getId());
            it.setUsername(username);
            it.setEnabled(1);
            it.setCreateDate(new Date());
            it.setCreateUserid(ouser.getId());
            it.setPassword(DigestUtils.md5DigestAsHex("123456".getBytes()));
            userService.saveAccountSelective(it);

            AuthRoleUser ru = new AuthRoleUser();
            ru.setId(UUIDUtils.randomUUID());
            ru.setUserid(ouser.getId());
            ru.setRoleid("0B355B0CF3914DED8839DFB3BE56B10E");
            roleService.insertUserRoles(ouser.getId(), new String[]{ru.getRoleid()});
        }
        ApiResult result = this.userService.verify(username);
        if (result.getStatus() == 200) {
            super.setSession(super.getSession().getId(), result.getResult());
        }
        return result;
    }

    /**
     * 账号验证
     *
     * @param username
     * @param password
     * @return
     */
    @PostMapping("/account/verify")
    @Weblog(description = "请求登录验证", method = WeblogEnum.UPDATE)
    public ApiResult verifyAccount(@NotBlank String username, @NotBlank String password, @NotBlank String vkey, @NotBlank String vcode, HttpServletRequest request) {
        String code = super.getSessionString(vkey);
        if (vcode.equalsIgnoreCase(code)) {
            ApiResult result = this.userService.verify(username, password);
            if (result.getStatus() == 200) {
                Date dt = new Date();
                SysLogLogin logLogin = new SysLogLogin();
                logLogin.setId(UUIDUtils.randomUUID());
                logLogin.setLoginIp(super.getIPAddress());
                logLogin.setLoginName(username);
                logLogin.setSessionId(super.getSession().getId());
                logLogin.setUrl(String.format("[%s]%s", request.getMethod(), request.getRequestURL().toString()));
                logLogin.setClientInfo(request.getHeader("User-Agent"));
                logLogin.setParamstring(JSON.toJSONString(request.getParameterMap()));
                logLogin.setQuerystring(request.getQueryString());
                logLogin.setLoginTime(dt);
                logLogin.setCreateDate(dt);
                logLogin.setCreateUsername(username);
                this.logService.saveSelective(logLogin);

                super.getSession().removeAttribute(vkey);
                super.setSession(super.getSession().getId(), result.getResult());
            }
            return result;
        } else {
            return new ApiResult(999, "验证码错误。");
        }
    }

    /**
     * 验证token是否有效
     *
     * @return
     */
    @PostMapping("/vtoken")
    @Weblog(description = "TOKEN验证", method = WeblogEnum.UPDATE)
    public ApiResult vtoken() {
        HttpSession session = super.getSession();
        Object ouser = session.getAttribute(session.getId());
        if (ouser == null) {
            return new ApiResult(999, "验证失败，凭证无效。");
        }
        return new ApiResult(200, "验证成功。", ouser);
    }

    /**
     * 退出
     *
     * @return
     */
    @PostMapping("/logout")
    @Weblog(description = "用户主动退出", method = WeblogEnum.UPDATE)
    public ApiResult logout() {
        HttpSession session = super.getSession();
        session.invalidate();
        return new ApiResult(200, "退出成功。");
    }

    /**
     * 修改账号密码
     *
     * @param username    登陆账号
     * @param newpassword 新密码，加密后。
     * @param oldpassword 旧密码，加密后。
     * @return
     */

    /**
     * 修改账号密码
     *
     * @param username    登陆账号
     * @param newpassword 新密码，加密后。
     * @param oldpassword 旧密码，加密后。
     * @param vkey        图形验证码key
     * @param vcode       图形验证码code
     * @return
     */
    @PostMapping("/update-password")
    @Weblog(description = "请求修改密码", method = WeblogEnum.UPDATE)
    public ApiResult updatePassword(@NotBlank String username, @NotBlank String newpassword, @NotBlank String oldpassword, @NotBlank String vkey, @NotBlank String vcode) {
        String code = super.getSessionString(vkey);
        if (vcode.equalsIgnoreCase(code)) {
            ApiResult ar = this.userService.updatePassword(username, newpassword, oldpassword);
            if (ar.getStatus() == 200) {
                super.getSession().removeAttribute(vkey);
            }
            return ar;
        } else {
            return new ApiResult(999, "验证码错误。");
        }
    }

    /**
     * 生成图形验证码
     *
     * @param vkey
     * @return
     */
    @PostMapping("/figure/vcode/generate")
    public ApiResult generateFigureVcode(String vkey) {
        if (StringUtils.isBlank(vkey)) {
            vkey = String.valueOf(SnowFlakeUtils.uniqueLong());
        }
        String vcode = VcodeUtils.randomVgcode();
        Map map = new HashMap<>();
        map.put("vkey", vkey);
        map.put("vcode", vcode);
        super.setSession(vkey, vcode);
        return new ApiResult(200, "图形验证码生成成功。", map);
    }

    /**
     * 获取短信验证码
     *
     * @param phoneNumbers
     * @return
     */
    @PostMapping("/sms/vcode/send")
    public ApiResult mobileVcode(@NotNull String[] phoneNumbers) {
        if (phoneNumbers.length <= 0) {
            throw new BizException("请输入手机号！");
        }

        OrgUser orgUser = userService.selectByMobile(phoneNumbers[0]);
        if (Objects.isNull(orgUser)) {
            return new ApiResult(999, "该手机号未注册用户，请联系管理员!");
        }

        String vscode = (String) redisTemplateUtil.get(phoneNumbers[0]);
        if (StringUtils.isNotBlank(vscode)) {
            return new ApiResult(999, "验证码已发送，请勿重发操作！");
        }

        String code = RandomNumberUtil.getRandomNumber();
        String[] params = {code, "2"};
        try {
            redisTemplateUtil.set(phoneNumbers[0], code, 120);
        } catch (Exception e) {
            redisTemplateUtil.del(phoneNumbers[0]);
            return new ApiResult(999, "生成短信验证码异常，请稍后再试");
        }
        try {
//            TmsSmsParam param = new TmsSmsParam();
//            param.setTemplateParam(params);
//            param.setPhoneParam(phoneNumbers);
//            param.setTemplateId(LOGIN_CODE_NOTICE_TEMPLATE_ID);
//            tencentSmsService.sendSmsProgress(param);
        }catch (Exception e) {
            redisTemplateUtil.del(phoneNumbers[0]);
            return new ApiResult(999, "验证码短信发送失败，请稍后再试");
        }
        Map map = new HashMap<>();
        map.put("vkey", String.valueOf(SnowFlakeUtils.uniqueLong()));
        map.put("vcode", phoneNumbers[0]);
        return new ApiResult(200, "获取验证码成功", map);
    }

    /**
     * 手机短信登录验证
     *
     * @return
     */
    @PostMapping("/mobile/verify")
    public ApiResult mobileVcodeVerify(@NotBlank String mobile, @NotNull String vkey, @NotBlank String vcode, HttpServletRequest request) {

        String vscode = (String) redisTemplateUtil.get(mobile);
        if (StringUtils.isBlank(vscode)) {
            return new ApiResult(999, "验证码已过期");
        }

        if (vcode.equalsIgnoreCase(vscode)) {
            ApiResult result = this.userService.verifyMobile(mobile);
            if (Objects.nonNull(result.getResult())) {
                Date dt = new Date();
                SysLogLogin logLogin = new SysLogLogin();
                logLogin.setId(UUIDUtils.randomUUID());
                logLogin.setLoginIp(super.getIPAddress());
                logLogin.setLoginName(((OrgUser)result.getResult()).getRealname());
                logLogin.setSessionId(super.getSession().getId());
                logLogin.setUrl(String.format("[%s]%s", request.getMethod(), request.getRequestURL().toString()));
                logLogin.setClientInfo(request.getHeader("User-Agent"));
                logLogin.setParamstring(JSON.toJSONString(request.getParameterMap()));
                logLogin.setQuerystring(request.getQueryString());
                logLogin.setLoginTime(dt);
                logLogin.setCreateDate(dt);
                logLogin.setCreateUsername(((OrgUser)result.getResult()).getRealname());
                this.logService.saveSelective(logLogin);
                super.setSession(super.getSession().getId(), result.getResult());
            }
            return new ApiResult(200, "手机短信登录成功", result.getResult());
        } else {
            return new ApiResult(999, "验证码错误。");
        }
    }
}
